package cn.tedu.justone.pack01;

/**
 * ZZ：JustOne
 * VX：Andylau2020smile
 * DY：JustOne2018
 * ZT：《》
 */
public class Demo31_Volatile禁止代码重排序简介 {

    //Volatile禁止代码重排序
    //Volatile禁止代码重排序
    //Volatile禁止代码重排序

    //
    //先来思考一个问题：
    // 三个人排队接水，A需要10分钟，B需要5分钟，C需要求1分钟，如果排队能让总时间更少？
    // 方案一：ABC，总用时为：A(10) + B(10+5) + C(10+5+1) = 10+15+16 = 41分钟
    // 方案二：BAC，总用时为：B(5) + A(5+10) + C(5+10+1) = 5+15+16 = 36分钟
    // ... ...
    // 方案N：CBA，总用时为：C(1) + B(1+5) + A(1+5+10) = 1+6+16 = 23分钟
    // 即让时间少的排到前面(此方案在数学中是可以被证明的)
    //

    // 1,什么是重排序？
    //   在Java程序运行时，JIT（Just-In-Time Compiler，即时编译器）为了优化程序的运行，
    //   可以动态地改变程序代码运行的顺序。比如有如下代码：
    //   ---A代码-重耗时
    //   ---B代码-轻耗时
    //   ---C代码-重耗时
    //   ---D代码-轻耗时
    //   在多线程的环境中，JIT有可能进行代码重排，重排后的代码顺序可能如下：
    //   ---B代码-轻耗时
    //   ---D代码-轻耗时
    //   ---A代码-重耗时
    //   ---C代码-重耗时
    //   这样做的主要原因是在CPU流水线中这4个指令是同时执行的，轻耗时的代码在很大程度上会先执行完，
    //   以让出CPU流水线资源供其他指令使用，所以代码重排是为了追求更高的程序运行效率。
    //
    // 2,重排序发生在没有依赖关系时，比如上面ABCD代码，BCD不依赖A的结果，CD不依赖AB的结果，
    //   D不依赖ABC的结果时，就会发生重排序，如果有依赖关系则不会重排序。
    //
    // 3,虽然代码重排序后能提高运行效率，但在有逻辑性的程序里很容易出现错误(后面会写例子来验证)，
    //   所以我们可以用volatile进禁止代码重排序。
    //
    // 4,Volatile关键字可以禁止代码重排序，比如有如下代码：
    //   ---A变量的操作
    //   ---B变量的操作
    //   ---volatile Z变量的操作
    //   ---C变量的操作
    //   ---D变量的操作
    //   那么这会有4种情况发生：
    //   ---1）AB可以重排序；
    //   ---2）CD可以重排序；
    //   ---3）AB不可以重排到Z的后面；
    //   ---4）CD不可以重排到Z的前面。
    //   也就是说，变量Z是一道屏障，是一堵墙，Z变量之前或之后的代码不可以跨越Z变量。
    //   synchronized关键字也具有同样的特性。

    //
}
